"""
数据验证模块
================

该模块负责验证读取和写入操作的参数和数据。
"""


from typing import Any, Dict, List, Union, Optional
from .typedef import AddressType, DataType
from ..utils.logger import get_logger,default_logger


class DataValidator:
    """数据验证器"""

    def __init__(self):
        """
        初始化数据验证器
        """
        pass

    @staticmethod
    def validate_read_address(address: AddressType) -> Dict[str, Any]:
        """
        验证读取地址

        Args:
            address: 地址

        Returns:
            Dict[str, Any]: 验证结果
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证读取地址: {address}")

        result = {
            'valid': True,
            'errors': []
        }

        # 检查地址是否为空
        if address is None:
            result['valid'] = False
            result['errors'].append('地址不能为空')
            logger.warning("读取地址验证失败: 地址不能为空")

        logger.debug(f"读取地址验证完成: {result}")
        return result

    @staticmethod
    def validate_read_addresses(addresses: List[AddressType]) -> Dict[str, Any]:
        """
        验证读取地址列表

        Args:
            addresses: 地址列表

        Returns:
            Dict[str, Any]: 验证结果
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证读取地址列表: {addresses}")

        result = {
            'valid': True,
            'errors': []
        }

        # 检查地址列表是否为空
        if not addresses:
            result['valid'] = False
            result['errors'].append('地址列表不能为空')
            logger.warning("读取地址列表验证失败: 地址列表不能为空")

        # 验证每个地址
        for i, address in enumerate(addresses):
            addr_result = DataValidator.validate_read_address(address)
            if not addr_result['valid']:
                result['valid'] = False
                result['errors'].extend([f'地址 {i}: {error}' for error in addr_result['errors']])
                logger.warning(f"读取地址列表中第{i}个地址验证失败: {addr_result['errors']}")

        logger.debug(f"读取地址列表验证完成: {result}")
        return result

    @staticmethod
    def validate_write_data_type(value: Any, data_type: DataType) -> bool:
        """
        验证写入数据类型

        Args:
            value: 要验证的值
            data_type: 期望的数据类型

        Returns:
            bool: 数据类型是否匹配
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证写入数据类型: value={value}, data_type={data_type}")

        # 如果数据类型为None或AUTO，表示自动推断，直接返回True
        if data_type is None or (hasattr(data_type, 'value') and data_type.value == 'auto'):
            logger.debug("数据类型为None或AUTO，验证通过")
            return True

        # 将DataType枚举转换为字符串进行比较
        if hasattr(data_type, 'value'):
            data_type_str = data_type.value.lower()
        else:
            data_type_str = str(data_type).lower()

        # 根据期望的数据类型验证值的类型
        validation_result = False
        if data_type_str in ['int', 'int16', 'int32', 'int64']:
            validation_result = isinstance(value, int)
        elif data_type_str in ['uint16', 'uint32', 'uint64']:
            validation_result = isinstance(value, int) and value >= 0
        elif data_type_str in ['float', 'double']:
            validation_result = isinstance(value, (int, float))
        elif data_type_str in ['bool', 'boolean']:
            validation_result = isinstance(value, bool)
        elif data_type_str in ['str', 'string']:
            validation_result = isinstance(value, str)
        elif data_type_str == 'byte':
            validation_result = isinstance(value, (bytes, bytearray))
        elif data_type_str in ['list', 'array']:
            validation_result = isinstance(value, (list, tuple))
        elif data_type_str in ['dict', 'dictionary']:
            validation_result = isinstance(value, dict)
        else:
            # 对于其他类型，暂时返回True，实际应用中可能需要更复杂的验证
            validation_result = True

        logger.debug(f"写入数据类型验证结果: {validation_result}")
        return validation_result

    @staticmethod
    def validate_write_data_range(value: Any, min_value: Optional[Any] = None,
                                max_value: Optional[Any] = None) -> bool:
        """
        验证写入数据范围

        Args:
            value: 要验证的值
            min_value: 最小值
            max_value: 最大值

        Returns:
            bool: 数据是否在范围内
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证写入数据范围: value={value}, min={min_value}, max={max_value}")

        # 如果没有指定范围限制，则验证通过
        if min_value is None and max_value is None:
            logger.debug("未指定范围限制，验证通过")
            return True

        try:
            # 检查最小值
            if min_value is not None and value < min_value:
                logger.warning(f"值 {value} 小于最小值 {min_value}")
                return False

            # 检查最大值
            if max_value is not None and value > max_value:
                logger.warning(f"值 {value} 大于最大值 {max_value}")
                return False

            logger.debug("写入数据范围验证通过")
            return True
        except TypeError:
            # 如果值不支持比较操作，则验证失败
            logger.warning(f"值 {value} 不支持比较操作")
            return False

    @staticmethod
    def validate_write_quality(value: Any, quality_check: bool) -> bool:
        """
        验证写入数据质量

        Args:
            value: 要验证的值
            quality_check: 是否进行质量检查

        Returns:
            bool: 数据质量是否合格
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证写入数据质量: value={value}, quality_check={quality_check}")

        # 如果不进行质量检查，则验证通过
        if not quality_check:
            logger.debug("不进行质量检查，验证通过")
            return True

        # 检查值是否为None
        if value is None:
            logger.warning("值为None，质量验证失败")
            return False

        # 检查字符串是否为空
        if isinstance(value, str) and len(value) == 0:
            logger.warning("字符串为空，质量验证失败")
            return False

        # 检查列表或元组是否为空
        if isinstance(value, (list, tuple)) and len(value) == 0:
            logger.warning("列表或元组为空，质量验证失败")
            return False

        # 检查字典是否为空
        if isinstance(value, dict) and len(value) == 0:
            logger.warning("字典为空，质量验证失败")
            return False

        # 对于数值类型，检查是否为NaN
        if isinstance(value, float) and str(value).lower() == 'nan':
            logger.warning("值为NaN，质量验证失败")
            return False

        logger.debug("写入数据质量验证通过")
        # 其他情况认为质量合格
        return True

    @staticmethod
    def validate_write_format(value: Any, format_spec: Optional[str] = None) -> bool:
        """
        验证写入数据格式

        Args:
            value: 要验证的值
            format_spec: 格式规范

        Returns:
            bool: 数据格式是否正确
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证写入数据格式: value={value}, format_spec={format_spec}")

        # 如果没有指定格式规范，则验证通过
        if format_spec is None:
            logger.debug("未指定格式规范，验证通过")
            return True

        # 检查字符串格式
        if format_spec == 'email' and isinstance(value, str):
            result = '@' in value and '.' in value
            logger.debug(f"邮箱格式验证结果: {result}")
            return result

        # 检查是否为十六进制字符串
        if format_spec == 'hex' and isinstance(value, str):
            try:
                int(value, 16)
                logger.debug("十六进制格式验证通过")
                return True
            except ValueError:
                logger.warning(f"字符串 {value} 不是有效的十六进制格式")
                return False

        # 检查是否为二进制字符串
        if format_spec == 'binary' and isinstance(value, str):
            try:
                int(value, 2)
                logger.debug("二进制格式验证通过")
                return True
            except ValueError:
                logger.warning(f"字符串 {value} 不是有效的二进制格式")
                return False

        # 检查是否为数字字符串
        if format_spec == 'numeric' and isinstance(value, str):
            result = value.isnumeric()
            logger.debug(f"数字字符串格式验证结果: {result}")
            return result

        # 检查是否为字母字符串
        if format_spec == 'alpha' and isinstance(value, str):
            result = value.isalpha()
            logger.debug(f"字母字符串格式验证结果: {result}")
            return result

        # 检查是否为字母数字字符串
        if format_spec == 'alphanumeric' and isinstance(value, str):
            result = value.isalnum()
            logger.debug(f"字母数字字符串格式验证结果: {result}")
            return result

        # 对于其他格式规范，暂时返回True
        logger.debug("其他格式规范，验证通过")
        return True

    @staticmethod
    def validate_read_config(config: Dict[str, Any]) -> Dict[str, Any]:
        """
        验证读取配置

        Args:
            config: 配置信息

        Returns:
            Dict[str, Any]: 验证结果
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证读取配置: {config}")

        result = {
            'valid': True,
            'errors': []
        }

        # 检查超时设置
        timeout = config.get('timeout')
        if timeout is not None and not isinstance(timeout, (int, float)):
            result['valid'] = False
            result['errors'].append('超时时间必须是数字类型')
            logger.warning("读取配置验证失败: 超时时间必须是数字类型")

        # 检查重试次数
        retry = config.get('retry')
        if retry is not None and (not isinstance(retry, int) or retry < 0):
            result['valid'] = False
            result['errors'].append('重试次数必须是非负整数')
            logger.warning("读取配置验证失败: 重试次数必须是非负整数")

        logger.debug(f"读取配置验证完成: {result}")
        return result

    @staticmethod
    def validate_write_all(address_info: Dict[str, Any], config: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行所有写入验证

        Args:
            address_info: 地址信息
            config: 配置信息

        Returns:
            Dict[str, Any]: 验证结果，包含验证状态和错误信息
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始执行所有写入验证: address_info={address_info}, config={config}")

        result = {
            'valid': True,
            'errors': []
        }

        try:
            # 获取地址信息中的值和数据类型
            values = address_info.get('values', [])
            data_types = address_info.get('data_types', [])
            addresses = address_info.get('addresses', [])

            # 获取配置信息
            expected_data_type = config.get('data_type')
            quality_check = config.get('quality_check', False)

            # 如果有值需要验证
            for i, value in enumerate(values):
                # 验证数据类型
                # 优先使用地址信息中的特定数据类型，其次使用配置中的通用数据类型
                data_type = expected_data_type
                if i < len(data_types):
                    data_type = data_types[i]
                elif len(data_types) == 1:
                    data_type = data_types[0]

                if data_type is not None and not DataValidator.validate_write_data_type(value, data_type):
                    address = addresses[i] if i < len(addresses) else f"index_{i}"
                    result['valid'] = False
                    result['errors'].append(f"地址 {address} 的数据类型验证失败")
                    logger.warning(f"写入数据类型验证失败: 地址 {address}")

                # 验证数据质量
                if not DataValidator.validate_write_quality(value, quality_check):
                    address = addresses[i] if i < len(addresses) else f"index_{i}"
                    result['valid'] = False
                    result['errors'].append(f"地址 {address} 的数据质量验证失败")
                    logger.warning(f"写入数据质量验证失败: 地址 {address}")

            # 如果验证失败，合并错误信息
            if not result['valid']:
                result['error'] = '; '.join(result['errors'])
                logger.warning(f"写入验证失败: {result['error']}")

            logger.debug(f"写入验证完成: {result}")
            return result
        except Exception as e:
            logger.error(f"执行写入验证时发生错误: {str(e)}", exc_info=True)
            result['valid'] = False
            result['errors'].append(f"验证过程中发生错误: {str(e)}")
            return result

    @staticmethod
    def validate_read_all(address_info: Dict[str, Any], config: Dict[str, Any]) -> Dict[str, Any]:
        """
        验证所有读取参数

        Args:
            address_info: 地址信息
            config: 配置信息

        Returns:
            Dict[str, Any]: 验证结果
        """
        logger = default_logger.getChild("DataValidator")
        logger.debug(f"开始验证所有读取参数: address_info={address_info}, config={config}")

        result = {
            'valid': True,
            'errors': []
        }

        try:
            # 验证地址
            addresses = address_info.get('addresses', [])
            addr_result = DataValidator.validate_read_addresses(addresses)
            if not addr_result['valid']:
                result['valid'] = False
                result['errors'].extend(addr_result['errors'])
                logger.warning(f"读取地址验证失败: {addr_result['errors']}")

            # 验证配置
            config_result = DataValidator.validate_read_config(config)
            if not config_result['valid']:
                result['valid'] = False
                result['errors'].extend(config_result['errors'])
                logger.warning(f"读取配置验证失败: {config_result['errors']}")

            logger.debug(f"读取验证完成: {result}")
            return result
        except Exception as e:
            logger.error(f"执行读取验证时发生错误: {str(e)}", exc_info=True)
            result['valid'] = False
            result['errors'].append(f"验证过程中发生错误: {str(e)}")
            return result